﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AES小工具
{
    public partial class FrmCRC32 : Form
    {
        public FrmCRC32()
        {
            InitializeComponent();
        }

        private void btnCheck_Click(object sender, EventArgs e)
        {
            if(cbText2Hex.Checked == false && cbText2Ascii.Checked == false)
            {
                MessageBox.Show("请选择数据格式！");
                return;
            }

            if (tbEmpty.Checked == true && cbText2Hex.Checked == true) {

                bool flag = HexStringCheck(tbText.Text.Trim());
                if (flag == false) {
                    MessageBox.Show("十六进制数据不正确，请检查！");
                    return;
                }
            }

            byte[] bytes = null;

            if (cbText2Hex.Checked == true)
                bytes = HexString2Bytes(tbText.Text.Trim());
            else
                bytes = Encoding.ASCII.GetBytes(tbText.Text.Trim());

            uint crcVal = Crc32(bytes);

            tbCrc32Result.Text = crcVal.ToString("X8");
        }

        /// <summary>
        /// 对十六进制字符进行检查
        /// </summary>
        /// <param name="hexStr"></param>
        /// <returns></returns>
        private bool HexStringCheck(string hexStr) {

            string[] strArr = hexStr.Split(' ');
            foreach (var str in strArr)
            {
                if (str.Length > 2) return false;
            }

            return true;
        }


        private UInt32 Crc32(byte[] data)
        {
            UInt32 crc32 = 0xFFFFFFFF;
            for (int i = 0; i < data.Length; i++)
                for (int k = 0; k < 8; k++)
                {
                    if (((crc32 >> 31) & 1) != ((data[i] >> (7 - k)) & 1))
                        crc32 = (crc32 << 1) ^ 0x04C11DB7;
                    else
                        crc32 = (crc32 << 1);
                }

            return crc32 ^ 0;
        }

        private byte[] HexString2Bytes(string text)
        {
            if (tbEmpty.Checked == true)
            {
                string[] textArr = text.Split(' ');
                byte[] bytes = new byte[textArr.Length];
                for (int index = 0; index < bytes.Length; index++)
                {
                    bytes[index] = Convert.ToByte(textArr[index], 16);
                }
                return bytes;
            }
            else
            {
                text = text.ToUpper();//转为大写形式
                char[] chArr = text.ToArray();
                byte[] textArr = new byte[chArr.Length];
                int len = 0;
                int index = 0;
                byte b = 0;
                while (index < chArr.Length)
                {
                    b = 0;
                    if (chArr[index] == ' ')
                    {
                        index++;
                        continue;
                    }
                    b = HexChar2Byte(chArr[index]);

                    index++;
                    if (chArr[index] == ' ')
                    {
                        textArr[len++] = b;
                        index++;
                        continue;
                    }
                    b = (byte)(b << 4);
                    b += HexChar2Byte(chArr[index]);
                    textArr[len++] = b;
                    index++;
                }
                byte[] result = new byte[len];
                Array.Copy(textArr, result, len);
                return result;
            }
        }

        private byte HexChar2Byte(char ch)
        {
            int index = ch - '0';
            if (index >= 0 && index <= 9)
            {
                return (byte)index;
            }
            else if ((ch - 'A') >= 0 && (ch - 'A') <= 5)
            {
                return (byte)((ch - 'A') + 10);
            }
            else
            {
                return 0;
            }
        }

        private void cbText2Hex_CheckedChanged(object sender, EventArgs e)
        {
            if (cbText2Hex.Checked == false) return;
            cbText2Ascii.Checked = !cbText2Hex.Checked;
            tbEmpty.Checked = cbText2Hex.Checked;
            tbEmpty.Enabled = cbText2Hex.Checked;
        }

        private void cbText2Ascii_CheckedChanged(object sender, EventArgs e)
        {
            if (cbText2Ascii.Checked == false) return;
            cbText2Hex.Checked = !cbText2Ascii.Checked;
            tbEmpty.Checked = !cbText2Ascii.Checked;
            tbEmpty.Enabled = cbText2Hex.Checked;
        }
    }
}
